package com.okay.volume

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioRecord
import android.media.MediaRecorder
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import androidx.core.app.ActivityCompat
import kotlin.math.abs
import kotlin.math.log10

/**
 * 检测麦克风收音的分贝
 */
class VolumeUtil {
    var context: Context? = null

    var volumeListener: VolumeListener?=null

    companion object {
        //输入源
        const val AUDIO_RECORDER_SOURCE = MediaRecorder.AudioSource.MIC

        //采样 44100Hz所有设备兼容
        const val AUDIO_RECORDER_SAMPLE = 8000

        //通道数 单通道
        const val AUDIO_RECORDER_CHANNEL = AudioFormat.CHANNEL_IN_MONO

        //音频比特位
        const val AUDIO_RECORDER_FORMAT = AudioFormat.ENCODING_PCM_16BIT

        //麦克风音量
        const val AUDIO_RECORDER_VOLUME_MESSAGE = 1001

        //打开麦克风失败
        const val AUDIO_RECORDER_ERROR_MESSAGE = 1002
    }

    private var mAudioRecorder: AudioRecord? = null

    private var mMinBufferSize = 0

    private var mAudioStart = false

    private var mHandler: Handler? = null

    constructor(context: Context) {
        this.context = context
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            (context as Activity).requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 1)
        }
        mHandler = object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                when (msg.what) {
                    AUDIO_RECORDER_VOLUME_MESSAGE -> {
                        volumeListener?.volumeNum((msg.obj as Double).toInt())

                    }
                    AUDIO_RECORDER_ERROR_MESSAGE -> {
                        Log.d("liaoww", "result : open mic error")
                        volumeListener?.volumeNum(0)
                    }
                }
            }
        }
    }



    /**
     * 开始检测音频
     */
     fun startAudioRecorder(volumeListener: VolumeListener) {
        this.volumeListener = volumeListener
        mAudioStart = true
        Thread {
            if (mAudioRecorder == null) {
                mAudioRecorder = createAudioRecorder()
            }
            mAudioRecorder?.run {
                try {
                    this.startRecording()
                    while (mAudioStart) {
                        val byteBuffer = ByteArray(mMinBufferSize)
                        val result =
                            this.read(byteBuffer, 0, mMinBufferSize)
                        Log.d("liaoww", "result : $result")
                        val volume = calculateVolume16bit(byteBuffer)
                        Log.d("liaoww", "volume : $volume")
                        mHandler?.sendMessage(Message.obtain().apply {
                            what = AUDIO_RECORDER_VOLUME_MESSAGE
                            obj = volume
                        })
                    }
                    try {
                        this.stop()
                        this.release()
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                } catch (e: Exception) {
                    createAudioError()
                    e.printStackTrace()
                    try {
                        this.stop()
                        this.release()
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
            mAudioRecorder = null
        }.start()
    }

    /**
     * 结束检测
     */
     fun stopRecorder() {
        mAudioStart = false
        mHandler?.removeCallbacksAndMessages(null)
    }

    private fun createAudioRecorder(): AudioRecord? {
        try {
            mMinBufferSize = AudioRecord.getMinBufferSize(
                AUDIO_RECORDER_SAMPLE,
                AUDIO_RECORDER_CHANNEL,
                AUDIO_RECORDER_FORMAT
            )

            context?.let {
                Log.e("liaoww", "mMinBufferSize : $mMinBufferSize")
                if (ActivityCompat.checkSelfPermission(it,
                        Manifest.permission.RECORD_AUDIO
                    ) == PackageManager.PERMISSION_GRANTED
                ) {
                    return AudioRecord(
                        AUDIO_RECORDER_SOURCE,
                        AUDIO_RECORDER_SAMPLE,
                        AUDIO_RECORDER_CHANNEL,
                        AUDIO_RECORDER_FORMAT,
                        mMinBufferSize
                    )

                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }

        return null
    }

    private fun createAudioError() {
        mHandler?.sendMessage(Message.obtain().apply {
            what = AUDIO_RECORDER_ERROR_MESSAGE
        })
    }

    private fun calculateVolume16bit(byteBuffer: ByteArray): Double {
        var sumVolume = 0.0
        var avgVolume = 0.0
        for (index in byteBuffer.indices step 2) {
            val v1 = byteBuffer[index].toInt() and 0xff
            val v2 = byteBuffer[index + 1].toInt() and 0xff
            var temp = v1 + (v2 shl 8) //小端
            if (temp >= 0x8000) {
                temp = 0xffff - temp
            }
            sumVolume += abs(temp)
        }
        avgVolume = sumVolume / byteBuffer.size / 2
        return log10(1 + avgVolume) * 10
    }

    interface VolumeListener{
        fun volumeNum(volume:Int)
    }

}